package ldh.im.rpc.buffer;

import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Function;

public class RpcBufferUtil {

    public static final Charset utf8 = Charset.forName("utf8");

    public static int writeString(RpcBuffer byteBuf, String str) {
        return writeString(byteBuf, str, utf8);
    }

    public static int writeString(RpcBuffer byteBuf, String str, Charset charset) {
        if (str == null) {
            byteBuf.writeShort((short)0);
            return 4;
        }
        byte[] bytes = str.getBytes(charset);
        byteBuf.writeShort((short)bytes.length);
        if (bytes.length > 0) {
            byteBuf.writeBytes(bytes);
        }
        return 4 + bytes.length;
    }

    public static String readString(RpcBuffer byteBuf) {
        return readString(byteBuf, utf8);
    }

    public static String readString(RpcBuffer byteBuf, Charset charset) {
        short length = byteBuf.readShort();
        return readString(byteBuf, length, charset);
    }

    public static String readString(RpcBuffer byteBuf, short length, Charset charset) {
        if (length > 0) {
            byte[] bytes = new byte[length];
            byteBuf.readBytes(bytes);
            return new String(bytes, charset);
        }
        return null;
    }

    public static <K, V>void writeMap(RpcBuffer rpcBuffer, Map<K, V> map, BiConsumer<RpcBuffer, K> keyConsumer,
                                      BiConsumer<RpcBuffer, V> valueConsumer) {
        if (map == null) {
            rpcBuffer.writeInt(0);
            return;
        }
        rpcBuffer.writeInt(map.size());
        for(Map.Entry<K, V> entry : map.entrySet()) {
            keyConsumer.accept(rpcBuffer, entry.getKey());
            valueConsumer.accept(rpcBuffer, entry.getValue());
        }
    }

    public static <K, V>Map<K, V> readMap(RpcBuffer rpcBuffer, Function<RpcBuffer, K> keyFun, Function<RpcBuffer, V> valueFun) {
        int size = rpcBuffer.readInt();
        if (size == 0) return new HashMap<>();

        Map<K, V> result = new HashMap<>();
        for(int i=0; i<size; i++) {
            K key = keyFun.apply(rpcBuffer);
            V value = valueFun.apply(rpcBuffer);
            result.put(key, value);
        }
        return result;
    }
}
